package ute.mvc.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import ute.mvc.dao.ClassDAO;
import ute.mvc.dao.TestAndQuizzDAO;
import ute.mvc.dto.ClassScoreDTO;
import ute.mvc.dto.QuestionDTO;
import ute.mvc.dto.TestDTO;
import ute.mvc.dto.TestPartDTO;
import ute.mvc.model.MyClass;
import ute.mvc.model.OpenCourse_Subject;
import ute.mvc.model.Question;
import ute.mvc.model.QuestionPool;
import ute.mvc.model.SubmittedTestAndQuizz;
import ute.mvc.model.TestAndQuizz;
import ute.mvc.model.TestAndQuizz_Student;
import ute.mvc.model.TestPart;
import ute.mvc.model.User;

@Service("testAndQuizzService")
public class TestAndQuizzServiceImpl implements TestAndQuizzService {

	@Autowired
	TestAndQuizzDAO testAndQuizzDAO;
	@Autowired
	ClassDAO classDAO;

	@Transactional
	public void addTestAndQuizz(TestAndQuizz testAndQuizz) {
		testAndQuizzDAO.addTestAndQuizz(testAndQuizz);
	}

	@Transactional
	public void updateTestAndQuizz(TestAndQuizz testAndQuizz) {
		testAndQuizzDAO.updateTestAndQuizz(testAndQuizz);

	}

	@Transactional
	public void deleteTestAndQuizz(TestAndQuizz testAndQuizz) {
		testAndQuizzDAO.deleteTestAndQuizz(testAndQuizz);
	}

	public TestAndQuizz getTestAndQuizz(String id) {
		// TODO Auto-generated method stub
		return testAndQuizzDAO.getTestAndQuizz(id);
	}

	public String getMaxIdInOpenCourseSubject(OpenCourse_Subject subject) {
		// TODO Auto-generated method stub
		return testAndQuizzDAO.getMaxIdInOpenCourseSubject(subject);
	}

	public List<TestAndQuizz> getTestBySubject(OpenCourse_Subject subject,
			User user) {
		// TODO Auto-generated method stub
		return testAndQuizzDAO.getTestBySubject(subject, user);
	}

	public List<MyClass> getClassByTestId(String testId) {
		// TODO Auto-generated method stub
		return testAndQuizzDAO.getClassByTestId(testId);
	}

	@Transactional
	public void updateClasses(String testId, String classes) {
		// TODO Auto-generated method stub
		String[] listClass = classes.substring(1).split(";");
		List<MyClass> lstAssignClass = new ArrayList<MyClass>();
		for (int i = 0; i < listClass.length; i++) {
			lstAssignClass.add(classDAO.getClassById(listClass[i]));
		}
		TestAndQuizz test = testAndQuizzDAO.getTestAndQuizz(testId);
		test.setListClass(lstAssignClass);
		testAndQuizzDAO.updateTestAndQuizz(test);
	}

	public TestAndQuizz_Student getTestAndQuizzByStudent(User student, String testId) {
		// TODO Auto-generated method stub
		List<TestAndQuizz_Student> lstStudentTest = new ArrayList<TestAndQuizz_Student>();
		lstStudentTest.addAll(student.getListSubmittedTest());
		
		for(TestAndQuizz_Student test: lstStudentTest){
			if(test.getTestAndQuizz().getTestAndQuizzID().equals(testId)){
				return test;
			}
		}
		return null;
	}

	public TestDTO getTestDTO(TestAndQuizz test) {
		// TODO Auto-generated method stub
		TestDTO testDTO = new TestDTO(test);
		List<TestPartDTO> listPartDTO = new ArrayList<TestPartDTO>();
		for(TestPart part : test.getListTestPart()){
			
			TestPartDTO partDTO = new TestPartDTO(part);
			if(part.getQuestionPool() == null){
				//Get all Question
				List<QuestionDTO> listQuestionDTO = new ArrayList<QuestionDTO>();
				List<Question> listQuestion = new ArrayList<Question>();
				listQuestion.addAll(part.getListQuestion());
				
				//Make random
				Collections.shuffle(listQuestion);
				//Get all question in part
				for (Question q : listQuestion) {
					listQuestionDTO.add(new QuestionDTO(q, true));
				}
				partDTO.setListQuestion(listQuestionDTO);
			}else{
				//Select Question
				List<QuestionDTO> listQuestionDTO = new ArrayList<QuestionDTO>();
				List<Question> listQuestion = new ArrayList<Question>();
				QuestionPool pool = part.getQuestionPool();
				listQuestion.addAll(pool.getListQuestion());
				
				//Make random
				Collections.shuffle(listQuestion);
				//Get number question in pool
				for(int i = 0; i < part.getNumberQuestion(); i++){
					listQuestionDTO.add(new QuestionDTO(listQuestion.get(i), true));
				}
				partDTO.setListQuestion(listQuestionDTO);
			}
			//Add part to listPart
			listPartDTO.add(partDTO);
		}
		testDTO.setListPart(listPartDTO);
		return testDTO;
	}

	public List<ClassScoreDTO> getScoreByClass(String testId, String classId) {
		// TODO Auto-generated method stub
		MyClass clazz = classDAO.getClassById(classId);
		List<User> lstStudent = new ArrayList<User>();
		lstStudent.addAll(clazz.getListStudent());
		
		List<ClassScoreDTO> lstScore = new ArrayList<ClassScoreDTO>();
		System.out.println(lstStudent.size());
		for(User u: lstStudent){
			
			//Get all test of a student
			List<TestAndQuizz_Student> lstTestStudent = new ArrayList<TestAndQuizz_Student>();
			lstTestStudent.addAll(u.getListSubmittedTest());
			ClassScoreDTO classScoreDTO = new ClassScoreDTO();
			classScoreDTO.setEmail(u.getEmail());
			classScoreDTO.setName(u.getName());
			for(TestAndQuizz_Student testStudent: lstTestStudent){
				
				// Get test of a student equal testId
				// Have test
				if(testStudent.getTestAndQuizz().getTestAndQuizzID().equals(testId)){
					List<SubmittedTestAndQuizz> lstSubmitted = new ArrayList<SubmittedTestAndQuizz>();
					lstSubmitted.addAll(testStudent.getListSubmittedTestAndQuizz());
					if(lstSubmitted.size() == 0)
						break;
					//find max point of this test
					SubmittedTestAndQuizz maxPointTest = lstSubmitted.get(0);
					for(SubmittedTestAndQuizz submittedTest: lstSubmitted){
						if(submittedTest.getPoint() > maxPointTest.getPoint()){
							maxPointTest = submittedTest;
						}
					}
					
					//Add to result	
					classScoreDTO.setNumberOfSubmission(lstSubmitted.size());
					classScoreDTO.setPoint(maxPointTest.getPoint());
					classScoreDTO.setStartTime(maxPointTest.getStartTime());
					classScoreDTO.setSubmittedTime(maxPointTest.getSubmittedTime());
				}
			}
			
			lstScore.add(classScoreDTO);
		}
		return lstScore;
	}
}
